#include "avr-builder.h"
#include "exceptions.h"
#include "operations.h"

void AVRBuilder::build (AVRSpec& spec, AVR& avr)
{
  avr._clock = new ClockSource;

  if (spec.flash_size () <= 0)
    throw SpecException ();
  avr._flash = new FlashMemory (spec.flash_size (), spec.flash_reg_map ());
  avr._clock->attach (*avr._flash);

  /* All avr micros shoule have 32 registers and 64 memory mapped io regs 
   * and the last ones should be the status reg and SP */
  avr._core = new AVRCore (*avr._flash, 0x5d);
  avr._clock->attach (*avr._core);
  DataBusMember::attach_member (*avr._core, *avr._flash);

  if (spec.sram_size () > 0) {
    avr._sram = new SRam (spec.sram_size (), spec.sram_map ());
    DataBusMember::attach_member (*avr._core, *avr._sram);
  }

  avr._regs = new SRam (32, 0);
  avr._regs->zero ();
  DataBusMember::attach_member (*avr._core, *avr._regs);

  list<CoreOperation::OP>::const_iterator beg = spec.ops_begin ();
  list<CoreOperation::OP>::const_iterator end = spec.ops_end ();

  CoreOperation *op;
  for (; beg != end; ++beg) {
    switch (*beg) {
      case CoreOperation::ADCADD: op = new ADCADDOperation; break;
      case CoreOperation::ADIW: op = new ADIWOperation; break;
      case CoreOperation::AND: op = new ANDOperation; break;
      case CoreOperation::ANDI: op = new ANDIOperation; break;
      case CoreOperation::ASR: op = new ASROperation; break;
      case CoreOperation::BSETCLR: op = new BSETCLROperation; break;
      case CoreOperation::BLDBST: op = new BLDBSTOperation; break;
      case CoreOperation::BRBCBRBS: op = new BRBCBRBSOperation; break;
      case CoreOperation::CALL: op = new CALLOperation; break;
      case CoreOperation::CBISBI: op = new CBISBIOperation; break;
      case CoreOperation::COM: op = new COMOperation; break;
      case CoreOperation::CPCPC: op = new CPCPCOperation; break;
      case CoreOperation::ORI: op = new ORIOperation; break;
      default: op = 0; break;
    }

    if (op) {
      avr._core->add_operation (op);
      op = 0;
    }
  }
}
